package com.spzx.order.receiver;

import com.rabbitmq.client.Channel;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.common.rabbit.constant.MqConst;
import com.spzx.common.rabbit.service.RabbitService;
import com.spzx.order.domain.OrderInfo;
import com.spzx.order.service.IOrderInfoService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName OrderReceiver
 * @Author 波
 * @Date 2024/8/13 20:27
 */
@Component
@Slf4j
public class OrderReceiver {
    @Autowired
    private IOrderInfoService orderInfoService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;

    /**
     * 延迟关闭订单消费者
     *
     * @param orderId
     * @throws IOException
     */
    @SneakyThrows
    @RabbitListener(queues = MqConst.QUEUE_CANCEL_ORDER)
    public void processCloseOrder(Long orderId, Message message, Channel channel) throws IOException {
        String lockKey = "mq:cancel:order:" + orderId;

        //1.获取分布式锁
        //1.1 获取不成功，说明消费一次了, 给mq一个确认，return ；
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(lockKey, "", 300, TimeUnit.SECONDS);
        if (!flag) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        try {
            //1.处理业务
            if (orderId != null) {
                log.info("【订单微服务】关闭订单消息：{}", orderId);
                orderInfoService.processCloseOrder(orderId);
                OrderInfo orderInfo = orderInfoService.getById(orderId);
                rabbitService.sendMessage(MqConst.EXCHANGE_PAYMENT_PAY, MqConst.ROUTING_PAYMENT_CLOSE, orderInfo.getOrderNo());
            }
            //2.手动应答
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            e.printStackTrace();
        }
    }

    /**
     * 支付成功后更改订单状态的消费者
     */
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = MqConst.EXCHANGE_PAYMENT_PAY,durable = "true"),
            value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY,durable = "true"),
            key = {MqConst.QUEUE_PAYMENT_PAY}
    ))
    public void changeOrderStatus(String orderNo, Message message, Channel channel) {
        String lockKey = "mq:changeOrderStatus:order:" + orderNo;
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(lockKey, orderNo, 300, TimeUnit.SECONDS);
        if (!flag) {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        try{
            //业务代码
            if(StringUtils.isNotEmpty(orderNo)){
                orderInfoService.changeOrderStatus(orderNo);
                //基于MQ通知扣减库存
                rabbitService.sendMessage(MqConst.EXCHANGE_PRODUCT, MqConst.ROUTING_MINUS, orderNo);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            }
        }catch (Exception e){
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            e.printStackTrace();
        }
    }


}
